
<template>
  <el-row>
    <!--<div @contextmenu.prevent="showMainMenu($event)">-->
    <div @contextmenu.prevent="showMainMenu($event)">
      <el-table
        ref="editTable"
        :empty-text="emptyText"
        :fit="fit"
        :data="tableData"
        style="width: 100%"
        :max-height="maxHeight"
        border
        highlight-current-row
        :span-method="objectSpanMethod"
        @cell-click="mouseClick"
        @row-contextmenu="rightClick"
        @cell-dblclick="mouseDBClick"
      >
        <!--<el-table-column v-if="columnData.length!==0" prop="type" width="50" label="序号" />-->
        <el-table-column
          v-for="(item,index) in columnData"
          :key="index"
          :prop="item.prop"
          :label="item.label"
          :min-width="item.width"
        >
          <template slot-scope="scope">
            <template v-if="item.attributes.type=='select'">
              <div v-show="scope.row['$edit$'+index]">
                <el-select
                  v-model="scope.row[item.prop]"
                  size="mini"
                  @blur="scope.row['$edit$'+index]=true"
                  @visible-change="selectVisible($event,item.prop,scope.row[item.prop],scope.row,item.attributes.selectData)"
                  @change="selectChange(item.prop,scope.row[item.prop],scope.row)"
                >
                  <el-option
                    v-for="(w,index) in item.attributes.selectData"
                    :key="index"
                    :label="w.value"
                    :value="w.key"
                  />
                </el-select>
              </div>
              <div v-show="!scope.row['$edit$'+index]">
                <div class="table-span" :title="scope.row[item.prop]">
                  <span>{{ renderer(item.prop,scope.row[item.prop]) }}</span>
                </div>
              </div>
            </template>

            <template v-else-if="item.attributes.type=='read'">
              <div class="table-span" :title="scope.row[item.prop]">
                <span>{{ scope.row[item.prop] }}</span>
              </div>
            </template>

            <template v-else-if="item.attributes.type=='input'">
              <el-row v-show="scope.row['$edit$'+index]">
                <el-col :span="24">
                  <el-input
                    v-model="scope.row[item.prop]"
                    size="mini"
                    style="width: 40%"
                    @input="changeInput(item.prop,scope.row)"
                  />
                </el-col>
                <!--<el-col :span="24" style="margin-top: 10px">-->
                <!--<el-button size="mini" @click="ensureEdit(scope.row)">确定</el-button>-->
                <!--</el-col>-->
              </el-row>
              <div class="table-span" :title="scope.row[item.prop]">
                <span v-show="!scope.row['$edit$'+index]">{{ scope.row[item.prop] }}</span>
              </div>
            </template>

            <template v-else-if="item.attributes.type ==='complexSelect'">
              <div v-show="scope.row['$edit$'+index] && scope.row[item.prop].pattern === 0">
                <el-row>

                  <el-col :span="24" style="margin-bottom: 10px">
                    <el-select
                      v-model="scope.row[item.prop].pattern"
                      size="mini"
                      style="width: 30%"
                    >
                      <el-option
                        v-for="(s,index) in patternOptions[scope.row['source']]"
                        :key="index"
                        :label="s.key"
                        :value="s.value"
                        :disabled="s.disabled"
                      />
                    </el-select>

                  </el-col>

                  <el-col :span="10">
                    <el-select
                      v-model="scope.row[item.prop].rule"
                      size="mini"
                      style="width: 77%"
                      @blur="scope.row['$edit$'+index]=true"
                      @visible-change="selectVisible($event,item.prop,scope.row[item.prop],scope.row,item.attributes.selectData)"
                      @change="selectChange(item.prop,scope.row[item.prop],scope.row)"
                    >
                      <el-option
                        v-for="(item,index) in item.attributes.selectData"
                        :key="index"
                        :label="item.value"
                        :value="item.key"
                      />
                    </el-select>
                  </el-col>

                  <el-col :span="10">
                    <el-input
                      v-show="scope.row['$edit$'+index]"
                      v-model="scope.row[item.prop].gte"
                      size="mini"
                      style="width: 50%"
                      @input="changeInput(item.prop,scope.row)"
                    />
                    {{ scope.row[item.prop].unit }}
                    <div class="table-span" :title="scope.row[item.prop].gte">
                      <span v-show="!scope.row['$edit$'+index]">{{ scope.row[item.prop].gte }}</span>
                    </div>
                  </el-col>

                  <!--<el-col :span="24" style="margin-top: 10px">-->
                  <!--<el-button size="mini" @click="ensureEdit(scope.row)">确定</el-button>-->
                  <!--</el-col>-->

                </el-row>

              </div>

              <div v-show="scope.row['$edit$'+index] && scope.row[item.prop].pattern === 1">
                <el-row>

                  <el-col :span="24" style="margin-bottom: 10px">
                    <el-select
                      v-model="scope.row[item.prop].pattern"
                      size="mini"
                      style="width: 30%"
                    >
                      <el-option
                        v-for="(s,index) in patternOptions[scope.row['source']]"
                        :key="index"
                        :label="s.key"
                        :value="s.value"
                        :disabled="s.disabled"
                      />
                    </el-select>

                  </el-col>

                  <el-col :span="12">
                    <el-input
                      v-show="scope.row['$edit$'+index]"
                      v-model="scope.row[item.prop].gte"
                      size="mini"
                      style="width: 30%"
                      @input="changeInput(item.prop,scope.row)"
                    />
                    {{ scope.row[item.prop].unit }}
                    <el-checkbox v-model="scope.row[item.prop].includeGte">包含</el-checkbox>

                    <span style="margin-left: 20px">-</span>
                    <div class="table-span" :title="scope.row[item.prop].gte">
                      <span v-show="!scope.row['$edit$'+index]">{{ scope.row[item.prop].gte }}</span>
                    </div>

                  </el-col>

                  <el-col :span="12">
                    <el-input
                      v-show="scope.row['$edit$'+index]"
                      v-model="scope.row[item.prop].lte"
                      size="mini"
                      style="width: 30%"
                      @input="changeInput(item.prop,scope.row)"
                    />
                    {{ scope.row[item.prop].unit }}
                    <el-checkbox v-model="scope.row[item.prop].includeLte">包含</el-checkbox>

                    <div class="table-span" :title="scope.row[item.prop].lte">
                      <span v-show="!scope.row['$edit$'+index]">{{ scope.row[item.prop].lte }}</span>
                    </div>
                  </el-col>

                  <!--<el-col :span="24" style="margin-top: 10px">-->
                  <!--<el-button size="mini" @click="ensureEdit(scope.row)">确定</el-button>-->
                  <!--</el-col>-->

                </el-row>

              </div>

              <div v-show="scope.row['$edit$'+index] && scope.row[item.prop].pattern === 2">
                <el-row>
                  <el-col :span="24" style="margin-bottom: 10px">
                    <el-select
                      v-model="scope.row[item.prop].pattern"
                      size="mini"
                      style="width: 30%"
                    >
                      <el-option
                        v-for="(s,index) in patternOptions[scope.row['source']]"
                        :key="index"
                        :label="s.key"
                        :value="s.value"
                        :disabled="s.disabled"
                      />
                    </el-select>

                  </el-col>

                  <el-col v-if="filterEditTextData[scope.row[item.prop].index].notIn.length === 0" :span="24">
                    <el-select
                      v-model="scope.row[item.prop].rule"
                      size="mini"
                      style="width: 30%"
                    >
                      <el-option
                        v-for="(item,index) in hasOptions"
                        :key="index"
                        :label="item.key"
                        :value="item.value"
                      />
                    </el-select>

                    <el-select
                      v-model="scope.row[item.prop].text"
                      multiple
                      placeholder="请选择"
                      size="mini"
                      style="width: 50%"
                    >
                      <el-option
                        v-for="s in filterEditTextData[scope.row[item.prop].index].contain"
                        :key="s.value"
                        :label="s.label"
                        :value="s.value"
                      />
                    </el-select>

                  </el-col>

                  <el-col v-else-if="filterEditTextData[scope.row[item.prop].index].notIn.length !== 0" :span="24">

                    <el-select
                      v-model="scope.row[item.prop].rule"
                      size="mini"
                      style="width: 30%"
                    >
                      <el-option
                        v-for="(item,index) in hasOptions"
                        :key="index"
                        :label="item.key"
                        :value="item.value"
                      />
                    </el-select>

                    <el-select
                      v-model="scope.row[item.prop].text"
                      multiple
                      placeholder="请选择"
                      size="mini"
                      style="width: 50%"
                    >

                      <el-option
                        v-for="s in filterEditTextData[scope.row[item.prop].index].notIn"
                        :key="s.value"
                        :label="s.label"
                        :value="s.value"
                      />
                    </el-select>

                  </el-col>

                  <!--<el-col :span="24" style="margin-top: 10px">-->
                  <!--<el-button size="mini" @click="ensureEdit(scope.row)">确定</el-button>-->
                  <!--</el-col>-->

                </el-row>
              </div>

              <div v-show="!scope.row['$edit$'+index] && scope.row[item.prop].pattern === 0">
                <div class="table-span" :title="scope.row[item.prop].gte">
                  <span>{{ renderer(item.prop,scope.row[item.prop].rule,'size') }}</span>
                  <span>{{ scope.row[item.prop].gte }}</span>
                  <span>{{ scope.row[item.prop].unit }}</span>
                </div>
              </div>

              <div v-show="!scope.row['$edit$'+index] && scope.row[item.prop].pattern === 1">
                <div class="table-span" :title="scope.row[item.prop].lte">
                  <span>{{ scope.row[item.prop].gte }}</span>
                  <span>{{ scope.row[item.prop].unit }}</span>
                  <span v-if="scope.row[item.prop].includeGte">(包含)</span>
                  <span v-else-if="!scope.row[item.prop].includeGte">(不包含)</span>
                  <span> - </span>
                  <span>{{ scope.row[item.prop].lte }}</span>
                  <span>{{ scope.row[item.prop].unit }}</span>
                  <span v-if="scope.row[item.prop].includeLte">(包含)</span>
                  <span v-else-if="!scope.row[item.prop].includeLte">(不包含)</span>
                </div>
              </div>

              <div v-show="!scope.row['$edit$'+index] && scope.row[item.prop].pattern === 2">
                <div class="table-span" :title="scope.row[item.prop]">
                  <span v-if="scope.row[item.prop].text.toString()">{{ scope.row[item.prop].text.toString() }}</span>
                  <span v-else> 无 </span>
                </div>
              </div>

            </template>
          </template>
        </el-table-column>

      </el-table>

      <div style="text-align:center;padding: 20px">
        评分结果 =
        <span v-for="(data,index) in displayList" :key="index">

          {{ data.source }} x {{ data.weight }}
          <span v-if="index !== displayList.length - 1 "> + </span>

        </span>
      </div>
    </div>
    <e-vue-contextmenu ref="setting-dialog" class="brightness-setting-dialog">
      <!--<div class="br-operation" @click="addRow">-->
      <!--<div class="icon"><i class="el-icon-circle-plus-outline" /></div>-->
      <!--<div class="text">新增一行</div>-->
      <!--</div>-->
      <!--<div class="br-operation" @click="inserRowBefore">-->
      <!--<div class="icon"><i class="el-icon-upload2" /></div>-->
      <!--<div class="text">当前行前面插入</div>-->
      <!--</div>-->
      <div class="br-operation" @click="inserRowAfter">
        <div class="icon"><i class="el-icon-download" /></div>
        <div class="text">新增一行</div>
      </div>
      <!--<div class="br-operation" @click="upRow">-->
      <!--<div class="icon"><i class="el-icon-top" /></div>-->
      <!--<div class="text">上移</div>-->
      <!--</div>-->
      <!--<div class="br-operation" @click="downRow">-->
      <!--<div class="icon"><i class="el-icon-bottom" /></div>-->
      <!--<div class="text">下移</div>-->
      <!--</div>-->
      <div class="br-operation" @click="deleteRow">
        <div class="icon"><i class="el-icon-remove-outline" /></div>
        <div class="text">删除当前行</div>
      </div>
      <!--<div class="br-operation" @click="deleteRows">-->
      <!--<div class="icon"><i class="el-icon-delete" /></div>-->
      <!--<div class="text">删除所有行</div>-->
      <!--</div>-->
    </e-vue-contextmenu>
  </el-row>
</template>

<script>
/**
   * @Author Jay
   * @Date 2021年5月14日14:00:34
   * @Description 基于ELEMENTUI的可编辑表格
   */
export default {

  name: 'EditTable',
  props: {

    filterEditTextData: {
      type: Array,
      required: false,
      default: () => []
    },

    // 初始化空数据
    initNum: {
      type: Number,
      required: false,
      default: 0
    },
    // 列头
    columnData: { type: Array,
      required: true
    },
    // 表格数据
    tableData: {
      type: Array,
      required: false,
      default: () => []
    },

    // 最大高度
    maxHeight: {
      type: Number,
      required: false
    },
    // 不可被编辑字段
    notIncluded: {
      type: Array,
      required: false,
      default: () => []
    },
    // 是否撑开
    fit: {
      type: Boolean,
      default: false
    },
    // 没有数据时提示
    emptyText: {
      type: String,
      required: false,
      default: () => '暂无数据'
    }
  },
  data () {
    return {

      displayList: [],

      filterTableData: [],
      has: '',
      pos: 0,
      spanArr: [],
      patternOptions: [
        {
          value: 0,
          key: '大小',
          disabled: false
        },
        {
          value: 1,
          key: '区间',
          disabled: false
        },
        {
          value: 2,
          key: '值',
          disabled: false
        }
      ],

      hasOptions: [
        {
          value: 0,
          key: '包含'
        },
        {
          value: 1,
          key: '等于'
        }
      ]

    }
  },
  computed: {},

  mounted () {
    // document.addEventListener('click', (e) => {
    //   console.info(e.target.parentNode)
    // })
  },

  created () {
    this.getSpanArr(this.tableData)
    this.initOptions(this.tableData)
    this.displayList = this.unique(this.tableData)

    for (let i = 0; i < this.tableData.length; i++) {
      this.$set(this.tableData[i], '$index$', i)
      for (let j = 0; j < this.columnData.length; j++) {
        if (this.notIncluded.length !== 0) {
          if (this.notIncluded.indexOf(this.columnData[j].prop) < 0) {
            this.$set(this.tableData[i], '$edit$' + j, false)
          }
        } else {
          this.$set(this.tableData[i], '$edit$' + j, false)
        }
      }
    }

    if (!(this.tableData && this.tableData.length)) {
      for (let i = 0; i < this.initNum; i++) {
        this.addRow()
      }
    }
  },
  methods: {

    // 初始化选择框
    initOptions (data) {
      this.patternOptions = {}

      data.forEach((item, index) => {
        if (!this.patternOptions[item.source]) {
          this.patternOptions[item.source] = []

          switch (item.targetType) {
            case 0:

              this.patternOptions[item.source].push(
                {
                  value: 2,
                  key: '值'
                }
              )

              this.tableData[index].condition.pattern = 2

              break
            case 1:

              this.patternOptions[item.source].push(
                {
                  value: 0,
                  key: '大小'
                },
                {
                  value: 1,
                  key: '区间'
                }
              )

              break
            case 2:

              this.patternOptions[item.source].push(
                {
                  value: 0,
                  key: '大小'
                },
                {
                  value: 1,
                  key: '区间'
                }
              )

              break
          }
        }
      })
    },

    // 去重
    unique (arr1) {
      const res = new Map()
      return arr1.filter((a) => !res.has(a.source) && res.set(a.source, 1))
    },

    // 判断当前元素与上一个元素是否相同
    getSpanArr (data) {
      this.spanArr = []
      for (var i = 0; i < data.length; i++) {
        if (i === 0) {
          this.spanArr.push(1)
          this.pos = 0
        } else {
          if (data[i].source === data[i - 1].source) {
            this.spanArr[this.pos] += 1
            this.spanArr.push(0)
          } else {
            this.spanArr.push(1)
            this.pos = i
          }
        }
      }
    },

    // 合并单元格
    objectSpanMethod ({ row, column, rowIndex, columnIndex }) { // 表格合并行
      if (columnIndex === 0) {
        const _row = this.spanArr[rowIndex]
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col
        }
      }
      if (columnIndex === 1) {
        const _row = this.spanArr[rowIndex]
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col
        }
      }
    },

    // 双击单元格
    mouseDBClick (row, column, cell, event) {
      for (let i = 0; i < this.columnData.length; i++) {
        row['$edit$' + i] = false
      }
    },

    // 点击单元格
    mouseClick (row, column, cell, event) {
      for (let i = 0; i < this.columnData.length; i++) {
        row['$edit$' + i] = false
      }
      if (this.$refs['setting-dialog']) { this.$refs['setting-dialog'].hideMenu() }
      for (let i = 0; i < this.columnData.length; i++) {
        if (this.columnData[i].prop === column.property) {
          row['$edit$' + i] = true
        } else {
          row['$edit$' + i] = false
        }
      }
    },
    // 鼠标移出单元格
    // mouseOut(row, column, cell, event) {
    //   for (let i = 0; i < this.columnData.length; i++) {
    //     row['$edit$' + i] = false
    //   }
    // },

    ensureEdit (data) {
      const d = { ...data }
      for (let i = 0; i < this.columnData.length; i++) {
        d['$edit$' + i] = false
      }
      this.tableData.splice(d.$index$, 1, d)
    },

    // 监听输入框
    changeInput (prop, row) {
      this.$emit('changeInput', prop, row)
    },
    // 监听下拉收起展开
    selectVisible (event, prop, key, row, datas) {
      if (!event) {
        for (let i = 0; i < this.columnData.length; i++) {
          row['$edit$' + i] = false
        }
      }
      this.$emit('selectVisible', event, prop, key, row)
    },
    // 监听下拉框变化
    selectChange (prop, key, row) {
      this.$emit('selectChange', prop, key, row)
    },
    // 表格右击
    rightClick (row, column, event) {
      this.rowIndex = row.$index$
    },
    // 菜单
    showMainMenu (e) {
      this.$refs['setting-dialog'].showMenu(e)
    },
    // new一个表格数据
    getNewRow () {
      const row = {}
      this.$set(row, '$index$', this.tableData.length)
      for (let i = 0; i < this.columnData.length; i++) {
        this.$set(row, this.columnData[i].prop, '')
      }
      for (let i = 0; i < this.columnData.length; i++) {
        if (this.notIncluded.length !== 0) {
          if (this.notIncluded.indexOf(this.columnData[i].prop) < 0) {
            this.$set(row, '$edit$' + i, false)
          }
        } else {
          this.$set(row, '$edit$' + i, false)
        }
      }
      return row
    },
    // 索引重置（不然删除等操作会有错误）
    reSort () {
      for (let i = 0; i < this.tableData.length; i++) {
        this.tableData[i].$index$ = i
      }
    },
    // 新增一行
    addRow () {
      const row = this.getNewRow()
      this.tableData.push(row)
      if (this.$refs['setting-dialog']) {
        if (this.$refs['setting-dialog']) { this.$refs['setting-dialog'].hideMenu() }
      }
    },
    // 向前插入
    inserRowBefore () {
      const row = this.getNewRow()
      this.tableData.splice(this.rowIndex, 0, row)
      this.reSort()
      if (this.$refs['setting-dialog']) { this.$refs['setting-dialog'].hideMenu() }
    },
    // 向后插入
    inserRowAfter () {
      const row = this.getNewRow()

      var pursue = { ...this.tableData.find(item => item.$index$ === this.rowIndex) }

      let p = 1
      console.info(this.tableData)
      console.info(pursue)

      pursue.targetType === 0 ? p = 2 : p = 0

      row.source = pursue.source
      row.weight = 1
      row.score = 1
      row.condition = {
        index: pursue.condition.index,
        text: [],
        lte: 1,
        gte: 0,
        includeLte: true,
        includeGte: true,
        unit: pursue.condition.unit,
        pattern: p,
        rule: 0
      }
      this.tableData.splice(this.rowIndex + 1, 0, row)

      this.reSort()

      this.getSpanArr(this.tableData)

      if (this.$refs['setting-dialog']) { this.$refs['setting-dialog'].hideMenu() }
    },
    // 上移
    upRow () {
      if (this.rowIndex !== 0) {
        const row = this.tableData.splice(this.rowIndex, 1)[0]
        this.tableData.splice(this.rowIndex - 1, 0, row)
        this.reSort()
      }
      if (this.$refs['setting-dialog']) { this.$refs['setting-dialog'].hideMenu() }
    },
    // 下移
    downRow () {
      if (this.rowIndex !== this.tableData.length - 1) {
        const row = this.tableData.splice(this.rowIndex, 1)[0]
        this.tableData.splice(this.rowIndex + 1, 0, row)
        this.reSort()
      }
      if (this.$refs['setting-dialog']) { this.$refs['setting-dialog'].hideMenu() }
    },
    // 删除当前行
    deleteRow () {
      this.tableData.splice(this.rowIndex, 1)
      if (this.$refs['setting-dialog']) { this.$refs['setting-dialog'].hideMenu() }

      this.reSort()
      this.getSpanArr(this.tableData)
      this.displayList = this.unique(this.tableData)
    },
    // 删除所选行
    deleteRows () {
      this.tableData.splice(0)
      if (this.$refs['setting-dialog']) { this.$refs['setting-dialog'].hideMenu() }
    },
    // 格式化（下拉框值进行key-value格式化）
    renderer (prop, value, pattern) {
      const me = this
      var renderer = null
      switch (pattern) {
        case 'size':
          for (let i = 0; i < this.columnData.length; i++) {
            if (this.columnData[i].prop === prop) {
              const selectData = this.columnData[i].attributes.selectData
              for (let j = 0; j < selectData.length; j++) {
                if (value === selectData[j].key) {
                  renderer = selectData[j].value
                }
              }
            }
          }
          return renderer || value
        case 'text':
          for (let i = 0; i < this.columnData.length; i++) {
            if (this.columnData[i].prop === prop) {
              const selectData = this.columnData[i].attributes.text
              for (let j = 0; j < selectData.length; j++) {
                if (value === selectData[j].key) {
                  renderer = selectData[j].value
                }
              }
            }
          }
          return renderer || value
      }
    }
  }
}
</script>
<style  scoped>
  .table-span {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
</style>
